import React, { Component, PropTypes } from 'react';
import echarts from 'echarts';
import { Button } from 'antd/lib/radio';
import shouldComponentUpdate from '../decorator/shouldComponentUpdate';
import { equal } from '../../utils/util';

const mapJson = require('./china.json');

echarts.registerMap('china', mapJson);

const sty = {
	but: {
		position: 'absolute',
		left: '1em',
		borderRadius: '4px',
		zIndex: 1
	}
};

const municipality = ['北京', '上海', '天津', '重庆'];
const provinceReg = /[省市]/;

function fullProvinceName(province) {
	if (municipality.includes(province)) return `${province}市`;
	return `${province}省`;
}

/**
 * 由于地图插件暂时不支持自定义，
 * 所以只需传data进来即可
 */
@shouldComponentUpdate
class MapChart extends Component {
	constructor(props, context) {
		super(props, context);
		this.chartResize = this.chartResize.bind(this);
		this.chartResizeTimeout = this.chartResizeTimeout.bind(this);
		this.onHandleGeoselectchanged = this.onHandleGeoselectchanged.bind(this);
		this.state = {
			loading: false
		};
	}

	componentDidMount() {
		this.myChart = echarts.init(this.chartDom, 'shine');
		this.setOption();
		if (this.props.select) {
			this.myChart.on('mapselectchanged', this.onHandleGeoselectchanged);
		}

		window.addEventListener('resize', this.chartResize);
		document.addEventListener('mouseup', this.chartResizeTimeout);

		setTimeout(() => {
			this.chartResize();
		}, 100);
		this.myChart.on('click', async ({ name }) => {
			const { provinceChange, mapName } = this.props;
			if (!provinceChange) return;
			if (this.state.loading) return;
			if (mapName) return;
			if (typeof provinceChange === 'function') provinceChange(fullProvinceName(name));
		});
	}

	componentDidUpdate(prevProps) {
		const keys = ['mapName', 'formatter', 'min', 'max', 'data'];
		const { loading } = this.state;
		if (!equal(prevProps, this.props, keys) && !loading) this.setOption();
	}

	componentWillUnmount() {
		window.removeEventListener('resize', this.chartResize);
		document.removeEventListener('mouseup', this.chartResizeTimeout);
	}

	async setOption(props = this.props) {
		const { mapName, formatter, min, max } = props;
		const name = (mapName || 'china').replace(provinceReg, '');
		const option = this.getOption();
		let json = echarts.getMap(name);
		if (!json) {
			this.setState({ loading: true });
			json = await window.fetch(`./map/${name}.json`).then(r => r.json());
			echarts.registerMap(name, json);
			this.setState({ loading: false });
		} else {
			json = json.geoJson;
		}
		option.series[0].mapType = name;
		option.series[0].data = this.getMapData(this.props.data, json);
		if (formatter) {
			option.tooltip.formatter = formatter;
		}
		option.visualMap.min = min;
		option.visualMap.max = max;
		this.myChart.setOption(option);
	}

	onHandleGeoselectchanged(item) {
		this.props.onSelect(item);
	}

	// 计算map 需要的格式的数据
	getMapData(data, map = mapJson) {
		const { mapName } = this.props;
		data = data.filter(d => d.name);
		const seriesData = map.features.map(f => ({ name: f.properties.name, value: 0 }));
		return seriesData.concat(!mapName ? data.map(d => {
			return {
				name: d.name.replace(provinceReg, ''),
				value: d.value
			};
		}) : data);
	}

	getOption() {
		const { chart: { map: { colors } } } = this.context.theme;
		return {
			title: {
				text: '',
				subtext: '',
				left: 'center',
			},
			tooltip: {
				trigger: 'item',
				formatter: '{b}:{c}',
			},
			visualMap: {
				min: this.props.min,
				max: this.props.max,
				left: '20px',
				top: 'bottom',
				text: [
					'高', '低',
				],
				calculable: true,
				show: true,
				color: colors || ['#ffec94', '#4cd8da', '#00badb'],
			},
			series: [
				{
					name: '',
					type: 'map',
					mapType: 'china',
					selectedMode: this.props.select ? 'single' : false,
					roam: false,
					label: {
						normal: {
							show: true,
						},
						emphasis: {
							show: false,
						},
					},
					data: [],
				},
			],
		};
	}

	chartResize() {
		this.myChart.resize();
	}

	chartResizeTimeout() {
		setTimeout(() => {
			this.myChart.resize();
		});
	}

	back = () => {
		const { provinceBack, data } = this.props;
		try {
			if (typeof provinceBack === 'function')provinceBack();
		} catch (error) {
			console.error(error);
		}
		this.setState({ name: null });
		const newOp = this.getOption();
		newOp.series[0].mapType = 'china';
		newOp.series[0].data = this.getMapData(data);
		this.myChart.setOption(newOp);
	}

	render() {
		const { height, width, mapName } = this.props;
		const style = { height: `${height}px`, width: `${width}px`, position: 'relative' };
		return (
			<div style={style}>
				{mapName ? <Button style={sty.but} onClick={this.back}>返回</Button> : null}
				<div
					style={style}
					ref={(c) => {
						this.chartDom = c;
					}}
				/>
			</div>
		);
	}
}

MapChart.defaultProps = {
	onSelect: () => { },
	min: 0,
	max: 100
};

MapChart.propTypes = {
	onSelect: PropTypes.func,
	data: PropTypes.array
};

MapChart.contextTypes = {
	theme: PropTypes.object
};

export default MapChart;
